package com.abkj.platform.tail.service.impl;

import com.abkj.platform.base.dao.warp.MapperWrap;
import com.abkj.platform.base.dao.warp.SQLType;
import com.abkj.platform.tail.command.CommandFactory;
import com.abkj.platform.tail.service.BaseService;
import com.abkj.platform.tail.service.DataService;
import com.abkj.platform.tail.service.TimerService;
import com.abkj.platform.util.PublicTool;
import com.abkj.platform.util.SerialPortUtil;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service("timerService")
public class TimerServiceImpl
  implements TimerService
{

  @Autowired
  private MapperWrap mapperWrap;

  @Autowired
  private DataService dataService;

  @Autowired
  private BaseService baseService;
  DatagramChannel channel = null;
  Selector selector = null;
  SerialPort serialPort = null;
  String com = "COM1";
  int rate = 9600;

  @Scheduled(cron="0 0/10 * * * ?")
  public void minite()
  {
    Calendar c = Calendar.getInstance();
    int hour = c.get(11);
    int min = c.get(12);
    List config = this.mapperWrap.findBySql("select * from config");
    Map con = (Map)config.get(0);
    this.com = con.get("com").toString();
    this.rate = Integer.parseInt(con.get("rate").toString());
    int scan = Integer.parseInt(con.get("scan").toString());
    if (min == 0) {
      if (hour == 0)
      {
        scanByTime(-1);
      } else if ((hour == 8) || (hour == 16)) {
        scanByTime(0);
      }
    }

    switch (scan) {
    case 0:
      if ((min == 0) && (hour % 6 == 0)) {
        scanByTime(1);
      }
      break;
    case 4:
      if ((min == 0) && (hour % 8 == 0)) {
        scanByTime(1);
      }
      break;
    case 1:
      scanByTime(1);
      break;
    case 2:
      if ((min == 0) || (min == 30)) {
        scanByTime(1);
      }
      break;
    case 3:
      if (min == 0) {
        scanByTime(1);
      }
      break;
    }

    close();
  }

  private void scanByTime(int type)
  {
    List list = new ArrayList();
    if ((type == 0) || (type == -1))
    {
      List ss3 = this.mapperWrap.findBySql("select id,code,info,'rain' as tname from rain where state=0 and id=1 ");
      list.addAll(ss3);
    }
    if (type == 1)
    {
      List ss = this.mapperWrap.findBySql("select id,code,info,'osmometer' as tname from osmometer where state=0 ");

      List ss2 = this.mapperWrap.findBySql("select id,code,info,type,num,'level' as tname from level where state=0 order by type");

      List ss4 = this.mapperWrap.findBySql("select id,code,info,'ultrasonic' as tname from ultrasonic where state=0 and id=1 ");
      list.addAll(ss);
      list.addAll(ss2);
      list.addAll(ss4);
    }
    for (int i = 0; i < list.size(); i++) {
      Map m = (Map)list.get(i);
      int id = NumberUtils.toInt(m.get("id").toString());
      int leveltype = NumberUtils.toInt(String.valueOf(m.get("type")));
      int levelnum = NumberUtils.toInt(String.valueOf(m.get("num")));
      int info = NumberUtils.toInt(m.get("info").toString());
      String code = m.get("code").toString();
      String tname = m.get("tname").toString();
      for (int count = 0; count < 3; count++) {
        int ret = scan(code, id, tname, info, type == -1, count, leveltype, levelnum);
        if ((ret != 1) && (ret != -1)) break;
        try {
          Thread.sleep(3000L);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }

      }

      try
      {
        Thread.sleep(1000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  private int scan(String code, int sid, String tablename, int old, boolean today, int index, int leveltype, int levelnum) {
    SerialPort serialPort = getSerialPort();
    if (serialPort == null) {
      System.out.println("串口获取失败！！！");
      return -2;
    }
    byte c;

    if (tablename.equals("rain"))
    {
      if (today)
        c = 27;
      else
        c = 26;
    } else {
      c = 16;
    }
    byte[] buffer;
    if ((tablename.equals("rain")) && (today))
      buffer = CommandFactory.getRainFontCommandBuff(code, c);
    else
      buffer = CommandFactory.getCommandBuff(code, c);
    PublicTool.printHexString(buffer);
    SerialPortUtil.write(serialPort, buffer);
    InputStream in = null;
    try {
      in = serialPort.getInputStream();
      byte[] ret = CommandFactory.getCommandReturn(in);
      int info = 0;
      if (ret != null) {
        PublicTool.printHexString(ret);
        System.out.println();
        if (CommandFactory.validate(ret)) {
          if (tablename.equals("rain"))
            this.dataService.rainData(ret);
          else
            this.dataService.operateWithScanData(ret, code, sid, tablename, leveltype, levelnum);
        }
        else {
          info = 1;
          if (index == 2) {
            String infos = "读取数据校验错误！！！传感器" + tablename + " code:" + code;
            System.out.println(infos);
            this.baseService.excuteBySql(SQLType.UPDATE, "insert into errorlog(content,createtime) values('" + infos + "',now())");
          }
        }
      } else {
        info = -1;
        if (index == 2) {
          String infos = "读取超时！！！传感器" + tablename + " code:" + code;
          this.baseService.excuteBySql(SQLType.UPDATE, "insert into errorlog(content,createtime) values('" + infos + "',now())");
          System.out.println(infos);
        }
      }
      if (info != old) {
        this.mapperWrap.excuteBySql(SQLType.UPDATE, "update " + tablename + " set info=" + info + " where id = " + sid);
      }
      return info;
    } catch (IOException|InterruptedException e) {
      e.printStackTrace();
    }return -2;
  }

  private SerialPort getSerialPort()
  {
    if (this.serialPort != null)
      return this.serialPort;
    try {
      Enumeration portList = CommPortIdentifier.getPortIdentifiers();
      while (portList.hasMoreElements()) {
        CommPortIdentifier portId = (CommPortIdentifier)portList.nextElement();
        if (portId.getPortType() == 1)
        {
          if (portId.getName().equals(this.com)) {
            this.serialPort = ((SerialPort)portId.open("Serial_Communication", 1000));
            this.serialPort.setSerialPortParams(this.rate, 8, 1, 0);
          } else {
            portId = null;
          }
        }
      }
    } catch (PortInUseException e) {
      this.serialPort = null;
      e.printStackTrace();
    } catch (UnsupportedCommOperationException e) {
      this.serialPort = null;
      e.printStackTrace();
    }
    System.out.println("打开串口：" + this.com);
    return this.serialPort;
  }

  private void close() {
    System.out.println("关闭串口：" + this.com);
    if (this.serialPort != null) {
      try {
        this.serialPort.getInputStream().close();
        this.serialPort.getOutputStream().close();
      } catch (IOException localIOException) {
      }
      this.serialPort.close();
      this.serialPort = null;
    }
  }
}